﻿using System;
using System.Collections.Generic;
using System.Reflection;
using System.Web;
using Newtonsoft.Json.Linq;
using TuyennvLibrary.Attributes;
using TuyennvLibrary.Reflection;
using TuyennvLibrary.ServerApi.Models;
namespace TuyennvLibrary.ServerApi.Controllers
{
    public class ApiController
    {
        private static Dictionary<string, string> getParameters(HttpRequest Request)
        {
            try
            {
                string param = Request["params"];

                Dictionary<string, string> parameters = new Dictionary<string, string>();
                if (!string.IsNullOrEmpty(param))
                {
                    param = param.TrimAll();
                    foreach (string item in param.Split(','))
                    {
                        parameters.Add(item, Request[item]);
                    }
                }
                return parameters;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public static object callApi(HttpRequest Request)
        {
            try
            {
                string cmd = Request["cmd"];
                if (string.IsNullOrEmpty(cmd))
                    return Code.cmdNull();
                object response;
                Code.CMD = cmd;
                if (cmd.ToLower() == "gcmapi")
                    response = callGcmApi(Request);
                else
                    response = callClassApi(Request);
                //response = new { response, cmd = cmd };
                try
                {
                    JObject jobject = JObject.FromObject(response);
                    jobject["cmd"] = cmd;
                    return jobject;
                }
                catch (Exception)
                {
                    return response;
                }
            }
            catch (Exception ex)
            {
                return new { code = -800, mesage = ex.Message };
            }
            //return Code.error();
        }
        private static object callClassApi(HttpRequest Request)
        {
            try
            {
                string dev = Request["dev"];

                string appid = Request["appid"];
                //kiem tra appid
                if (string.IsNullOrEmpty(appid))
                    return Code.appidNull();
                Application app = new ApplicationModel().GetByID(appid);
                if (string.IsNullOrEmpty(app.appid))
                    return Code.appidFalse();
                bool auth = true;
                if (string.IsNullOrEmpty(dev))
                {
                    //Kiem tra key
                    string key_request = Request["key"];
                    if (string.IsNullOrEmpty(key_request))
                        return Code.keyNull();
                    string requestid = Request["requestid"];
                    //kiem tra requestid
                    if (string.IsNullOrEmpty(requestid))
                        return Code.requestidNull();

                    auth = Authentication(key_request, app.private_key, app.appid, requestid);
                }
                //auth = true;
                if (auth)
                {
                    Dictionary<string, string> parameters = getParameters(Request);
                    string method = Request["cmd"];
                    if (string.IsNullOrEmpty(app.file_dll))
                    {
                        return new ServerAPI(appid).callApi(app.class_api, method, parameters);
                    }
                    else
                    {
                        string pathdll = Config.Server.MapPath(Config.DirFileDLL + app.file_dll);
                        ////string pathdll = Config.server.MapPath(app.file_dll);
                        //string pathdll = Assembly.GetExecutingAssembly().Location + "\\" + app.file_dll;
                        return new ServerAPI(appid).callApi(pathdll, app.class_api, method, parameters);
                    }

                }
                else
                {
                    return Code.notPermisssion();
                }
            }
            catch (Exception ex)
            {
                return new { code = Code.ERROR, message = ex.Message };
            }

        }
        private static object callGcmApi(HttpRequest Request)
        {
            try
            {
                string dev = Request["dev"];

                string appid = Request["appid"];
                //kiem tra appid
                if (string.IsNullOrEmpty(appid))
                    return Code.appidNull();
                Application app = new ApplicationModel().GetByID(appid);
                if (string.IsNullOrEmpty(app.appid))
                    return Code.appidFalse();
                bool auth = true;
                if (string.IsNullOrEmpty(dev))
                {
                    string key_request = Request["key"];
                    //Kiem tra key
                    if (string.IsNullOrEmpty(key_request))
                        return Code.keyNull();
                    string requestid = Request["requestid"];
                    //kiem tra requestid
                    if (string.IsNullOrEmpty(requestid))
                        return Code.requestidNull();
                    auth = Authentication(key_request, app.private_key, app.appid, requestid);
                }
                //auth = true;
                if (auth)
                {
                    Dictionary<string, string> parameters = getParameters(Request);
                    string method = Request["method"];
                    if (string.IsNullOrEmpty(method))
                        return Code.methodNull();
                    return new ServerAPI().callApi("ServerApi.ClassApi.GcmApi", method, parameters);
                }
                else
                {
                    return Code.notPermisssion();
                }
            }
            catch (Exception ex)
            {
                return new { code = Code.ERROR, message = ex.Message };
            }


        }
        private static bool Authentication(string key_request, string private_key, string appid, string requestid)
        {
            string key = ServerApi.Util.ApiUtilities.md5(private_key + appid + requestid);
            if (key != key_request)
                return false;
            return true;
        }
        private static DescriptionMethod getDescriptionMethod(Type myType, MethodInfo method, string appid, string urlapi)
        {
            string parameters = string.Empty;
            string parameterdev = string.Empty;
            string sParams = string.Empty;
            List<AttributeDescriptionMethod> listAttribute;
            DescriptionMethod description = new DescriptionMethod(method);
            AttributeDescriptionMethod[] attributes = (AttributeDescriptionMethod[])Attribute.GetCustomAttributes(method, typeof(AttributeDescriptionMethod));
            AttributeExpireMethod attributeExpireMethod = (AttributeExpireMethod)Attribute.GetCustomAttribute(method, typeof(AttributeExpireMethod));
            if (attributes != null && attributes.Length > 0)
            {
                listAttribute = new List<AttributeDescriptionMethod>();
                listAttribute.AddRange(attributes);
                listAttribute.Sort();
                foreach (AttributeDescriptionMethod attribute in listAttribute)
                {
                    description.Description += string.Format("{0}<br />", attribute.ToString());
                }

            }
            ParameterInfo[] parammeterArr = method.GetParameters();

            for (int i = 0; i < parammeterArr.Length; i++)
            {
                parameters += string.Format("{0} {1}{2}", parammeterArr[i].ParameterType.Name, parammeterArr[i].Name, (i < parammeterArr.Length - 1) ? ", " : "");
                if (!parammeterArr[i].Name.ToLower().Equals("appid"))
                {
                    parameterdev += string.Format("{0}=[{1}]{2}", parammeterArr[i].Name, parammeterArr[i].Name, (i < parammeterArr.Length - 1) ? "&" : "");
                }
                sParams += string.Format("{0}{1}", parammeterArr[i].Name, (i < parammeterArr.Length - 1) ? "," : "");
            }
            string request = string.Format("?dev=true&appid=" + appid + "&cmd={0}{1}{2}", method.Name, (string.IsNullOrEmpty(sParams)) ? "" : "&amp;params=" + sParams, (string.IsNullOrEmpty(parameterdev)) ? "" : "&" + parameterdev);
            description.Name = string.Format("<strong>{0}({1})</strong>", method.Name, parameters);
            description.LinkDev = urlapi + request;
            description.DeclaringType = method.GetBaseDefinition().DeclaringType;
            description.Inherit = !(description.DeclaringType.ToString() == myType.ToString());
            if (attributeExpireMethod != null)
            {
                description.Expire = attributeExpireMethod.Expire;
            }
            //if (description.Expire == true)
            //{
            //    description.Name = description.Name ";
            //}
            return description;
        }
        public static List<DescriptionMethod> getListDescriptionApi(string pathDll, string classApi, string appid, string urlapi)
        {
            string result = string.Empty;
            List<DescriptionMethod> listDescription = new List<DescriptionMethod>();
            //Xac dinh kieu cua class

            Type myTypeObj;
            try
            {
                if (!string.IsNullOrEmpty(pathDll))
                {
                    var dll = Assembly.LoadFile(pathDll);
                    myTypeObj = dll.GetType(classApi);
                }
                else
                {
                    myTypeObj = Type.GetType(classApi);
                }
                MethodInfo[] methods = myTypeObj.GetMethods();
                if (methods != null && methods.Length > 0)
                {

                    foreach (MethodInfo method in methods)
                    {
                        if (method.ReturnType.Equals(typeof(object)))
                        {
                            try
                            {
                                DescriptionMethod obj = getDescriptionMethod(myTypeObj, method, appid, urlapi);
                                obj.Id = listDescription.Count;
                                listDescription.Add(obj);
                            }
                            catch (Exception)
                            {

                            }
                        }
                    }
                }

            }
            catch (Exception)
            {
            }
            return listDescription;
        }
    }
}